#pragma once

#include <string>
#include <memory>
#include <vector>

#include <rtc_base/byte_buffer.h>    
#include <rtc_base/socket_address.h>

namespace xrtc {

const size_t k_stun_header_size = 20; // STUN消息头部大小
const size_t k_stun_attribute_header_size = 4; // STUN属性头部大小
const size_t k_stun_transaction_id_offset = 8; // STUN事务ID偏移
const size_t k_stun_transaction_id_length = 12; // STUN事务ID长度
const uint32_t k_stun_magic_cookie = 0x2112A442; // STUN Magic Cookie 固定取值
const size_t k_stun_magic_cookie_length = sizeof(k_stun_magic_cookie);
const size_t k_stun_message_integrity_size = 20; // STUN消息完整性大小

// STUN消息类型
enum StunMessageType {
    STUN_BINDING_REQUEST = 0x0001,
    STUN_BINDING_RESPONSE = 0x0101,
};

// STUN属性类型
enum StunAttributeType {
    STUN_ATTR_USERNAME = 0x0006,
    STUN_ATTR_MESSAGE_INTEGRITY = 0x0008,
    STUN_ATTR_XOR_MAPPED_ADDRESS = 0x0020,
    STUN_ATTR_PRIORITY = 0x0024,
    STUN_ATTR_FINGERPRINT = 0x8028,
};

// STUN属性值类型
enum StunAttributeValueType {
    STUN_VALUE_UNKNOWN = 0,
    STUN_VALUE_UINT32,
    STUN_VALUE_BYTE_STRING,
};

// STUN错误码
enum StunErrorCode {
    STUN_ERROR_BAD_REQUEST = 400,
    STUN_ERROR_UNATHORIZED = 401,
    STUN_ERROR_SERVER_ERROR = 500,
};

// STUN地址族
enum StunAddressFamily {
    STUN_ADDRESS_UNDEF = 0,
    STUN_ADDRESS_IPV4 = 1,
    STUN_ADDRESS_IPV6 = 2,
};

// STUN错误描述信息
extern const char STUN_ERROR_REASON_BAD_REQUEST[];
extern const char STUN_ERROR_REASON_UNATHORIZED[];
extern const char STUN_ERROR_REASON_SERVER_ERROR[];

// 将STUN方法转换为字符串
std::string stun_method_to_string(int type);

// STUN属性的基类
class StunAttribute {
public:
    virtual ~StunAttribute() = default;

    int getType() const { return m_type; }
    size_t getLength() const { return m_length; }

    void set_length(size_t length) { m_length = length; }
    void set_type(uint16_t type) { m_type = type; }

    
    // 工厂方法：根据传入的类型和长度创建STUN属性
    static StunAttribute* createStunAttribute(StunAttributeValueType value_type, uint16_t type, uint16_t length, 
                                            void* owner);

    virtual bool read(rtc::ByteBufferReader* buf) = 0;
    virtual bool write(rtc::ByteBufferWriter* buf) = 0;

protected:
    StunAttribute(uint16_t type, uint16_t length);

    // 处理4字节偏移对齐的情况
    void consume_padding(rtc::ByteBufferReader* buf);    
    // 写入4字节偏移对齐的情况
    void write_padding(rtc::ByteBufferWriter* buf);
    const StunAttribute* _get_attribute(uint16_t type);

public:
    uint16_t m_type;
    uint16_t m_length;
};

// STUN消息的属性类 无符号32位整数类型
class StunUInt32Attribute : public StunAttribute {
public:
    StunUInt32Attribute(uint16_t type) : StunAttribute(type, SIZE), m_bits(0) {}
    StunUInt32Attribute(uint16_t type, uint32_t value) : StunAttribute(type, SIZE), m_bits(value) {}
    ~StunUInt32Attribute() override = default;

    uint32_t get_value() const { return m_bits; }
    void set_value(uint32_t value) { m_bits = value; }

    bool read(rtc::ByteBufferReader* buf) override;
    bool write(rtc::ByteBufferWriter* buf) override;

public:
    static const size_t SIZE = 4;

private:
    uint32_t m_bits;
};

// STUN消息的属性类 字符串类型
class StunByteStringAttribute : public StunAttribute {
public:
    StunByteStringAttribute(uint16_t type, uint16_t length);
    StunByteStringAttribute(uint16_t type, const std::string& str);
    ~StunByteStringAttribute() override;
    

    void copy_bytes(const char* bytes, size_t length);

    bool read(rtc::ByteBufferReader* buf) override;
    bool write(rtc::ByteBufferWriter* buf) override;

    std::string get_string() const { return std::string(m_bytes, getLength()); }

private:
    void _set_bytes(char* bytes);
    
private:
    char* m_bytes = nullptr;
};

// STUN地址属性
class StunAddressAttribute : public StunAttribute {
public:
    StunAddressAttribute(uint16_t type, const rtc::SocketAddress& addr);
    ~StunAddressAttribute() = default;
    
    // 设置地址
    void set_address(const rtc::SocketAddress& addr);
    // 获取地址族
    StunAddressFamily get_family();


    bool read(rtc::ByteBufferReader* buf) override;
    // 写入STUN地址属性
    bool write(rtc::ByteBufferWriter* buf) override;

public:
    const size_t SIZE_UNDEF = 0;
    const size_t SIZE_IPV4 = 8;
    const size_t SIZE_IPV6 = 20;

protected:
    rtc::SocketAddress m_address;
};

class StunXorAddressAttribute : public StunAddressAttribute {
public:
    StunXorAddressAttribute(uint16_t type, const rtc::SocketAddress& addr);
    ~StunXorAddressAttribute() = default;

    // 写入XOR-MAPPED-ADDRESS属性
    bool write(rtc::ByteBufferWriter* buf) override;

private:
    // 获取XOR-IP地址
    rtc::IPAddress _get_xored_ip();
};

// STUN消息
class StunMessage {
public:
    // 消息完整性状态
    enum class MessageIntegrityStatus {
        // 未设置
        k_not_set = 0,
        // 没有完整性   
        k_no_integrity = 1,
        // 完整性OK
        k_integrity_ok = 2,
        // 完整性BAD
        k_integrity_bad = 3,
    };

    StunMessage();
    ~StunMessage() = default;

    int getMessageType() const { return m_message_type; }
    int getMessageLength() const { return m_message_length; }
    const std::string& get_transaction_id() const { return m_transaction_id; }

    void set_message_type(uint16_t message_type) { m_message_type = message_type; }
    void set_message_length(uint16_t message_length) { m_message_length = message_length; }
    void set_transaction_id(const std::string& transaction_id) { m_transaction_id = transaction_id; }

    // 验证Fingerprint属性
    static bool validate_fingerprint(const char* data, size_t size);
    // 添加Fingerprint属性
    bool add_fingerprint();


    // 调用_validate_message_integrity_of_type()验证消息完整性的状态
    MessageIntegrityStatus validate_message_integrity(const std::string& pwd);
    // 添加消息完整性属性(调用_add_message_integrity_of_type())
    bool add_message_integrity(const std::string& password);

    // 添加STUN属性
    void add_attribute(std::unique_ptr<StunAttribute> attr);

    // 获取STUN属性值类型
    StunAttributeValueType get_attribute_value_type(int type);

    // 读取STUN消息
    bool read_from(rtc::ByteBufferReader* buf);
    bool write(rtc::ByteBufferWriter* buf) const;


    // 获取uint32类型STUN属性
    const StunUInt32Attribute* get_uint32(uint16_t type);
    // 获取字符串类型STUN属性
    const StunByteStringAttribute* get_byte_string_attribute(uint16_t type);

private:
    // 根据传入的类型和长度调用工厂方法创建属性对象
    StunAttribute* _create_attribute(uint16_t type, uint16_t length);
    // 获取指定Type的STUN属性
    const StunAttribute* _get_attribute(uint16_t type);

    // 解析MIP属性，验证消息完整性的状态
    bool _validate_message_integrity_of_type(uint16_t mi_attr_type, size_t mi_attr_size, 
        const char* data, size_t size, const std::string& password);
    
    // 添加消息完整性属性
    bool _add_message_integrity_of_type(uint16_t attr_type,
        uint16_t attr_size, const char* key, size_t len);

private:
    uint16_t m_message_type; // 消息类型
    uint16_t m_message_length; // 消息长度
    std::string m_transaction_id; // 事务ID
    std::vector<std::unique_ptr<StunAttribute>> m_attributes; // 属性
    MessageIntegrityStatus m_message_integrity_status = MessageIntegrityStatus::k_not_set; // 消息完整性状态
    std::string m_pwd;
    std::string m_buffer; // 保存STUN消息内容的缓冲区

};

} // namespace xrtc